﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using SiGeSIB.GUI.Common;
using SiGeSIB.Data.Management;
using SiGeSIB.Services;
using SiGeSIB.Data.Common;
using SiGeSIB.Business.Management;
using SiGeSIB.Data.Security;

namespace SiGeSIB.GUI.Management
{
#if DESIGN
	public partial class FEditMember : FormRedirector.FEditMember
#else
	public partial class FEditMember : FGenericEditor<Contributor>
#endif
	{
        #region Constructors
        public FEditMember()
            : this(EFormState.Edit, EContributorType.Contributor, -1)
        { }
        public FEditMember(EFormState initialState, EContributorType type, int id)
            : base(initialState, id)
        {
            InitializeComponent();
            InitialState = initialState;
            Type = type;
            _Id = id;

            #region Inicializando o tipo da tela
            if (type == EContributorType.Contributor)
            {
                if (initialState == EFormState.View)
                {
                    this.Text = "Edição de contribuinte";
                    _IdleMessage = "Visualize as informações do contribuinte.";
                }
                else
                {
                    this.Text = "Inserção de contribuinte";
                    _IdleMessage = "Insira as informações do contribuinte.";
                }

                tlpGeneralInformation.Controls.Remove(panBornDate);
                tlpGeneralInformation.Controls.Remove(panCivilState);
                tlpGeneralInformation.Controls.Remove(panOriginChurch);
                tblContributor.Controls.Remove(gbxMembersy);
            }
            else if (type == EContributorType.Visitor)
            {
                if (initialState == EFormState.View)
                {
                    this.Text = "Edição de visitante";
                    _IdleMessage = "Visualize as informações do visitante.";
                }
                else
                {
                    this.Text = "Inserção de visitante";
                    _IdleMessage = "Insira as informações do visitante.";
                }

                tblContributor.Controls.Remove(gbxMembersy);
            }
            else
            {
                if (initialState == EFormState.View)
                {
                    this.Text = "Edição de membro";
                    _IdleMessage = "Visualize as informações do membro.";
                }
                else
                {
                    this.Text = "Inserção de membro";
                    _IdleMessage = "Insira as informações do membro.";
                }

                tlpGeneralInformation.Controls.Remove(panOriginChurch);
            }
            gbxGeneralInformation.Height = tlpGeneralInformation.Height + 25;
            #endregion

            #region ErrorController
            _Controller.AddErrorLabel("InvalidName", new Control[] { lblName, txtName });
            _Controller.AddErrorLabel("InvalidDisruptionType", new Control[] { lblDisruption, cboDisruption });
            _Controller.AddErrorLabel("InvalidDocumentNumber", new Control[] { lblDocumentNumber, mtbDocumentNumber });
            _Controller.AddErrorLabel("InvalidPhoneNumber", new Control[] { lblPhone, mtbPhone });
            _Controller.AddErrorLabel("InvalidCellPhoneNumber", new Control[] { lblCellPhone, mtbCellPhone });
            _Controller.AddErrorLabel("InvalidMembershipDate", new Control[] { lblMembersyDate, dtpMembersyDate });
            #endregion

            #region FieldsToLock
            FieldsToLock = new List<object>()
			{
				lblName,
				lblPhone,
				lblMembersyType,
				lblMembersyDate,
				lblDocumentType,
				lblDocumentNumber,
				lblDisuptionDate,
				lblCivilState,
				lblChurchOrigin,
				lblCellPhone,
				lblBornDate,
				txtChurchOrigin,
				txtName,
				mtbCellPhone,
				mtbDocumentNumber,
				mtbPhone,
				cboMembersyType,
				cboDisruption,
				cbxCivilState,
				cbxDocumentType,
				uAddressControl1,
				dtpBornDate,
				dtpDisruptionDate,
				dtpMembersyDate
			};
            #endregion
        } 
        #endregion

		#region Attributes
		private IManagementServicesProvider _Provider;
		#endregion

		#region Properties
		public EContributorType Type { get; set; }
		public IManagementServicesProvider Provider
		{
			get
			{
				return _Provider != null ?
					_Provider
					: _Provider = _Manager.ServicesProvider.CreateManagementServicesProvider();
			}
		}

		protected override bool HasEditPermission
		{
			get
			{
				return
					Manager.Instance.LoggedUser.IsAdmin
					||
					(
						Manager.Instance.LoggedUser.Permissions
						&
						EPermissions.ManageMember
					) != EPermissions.None;
			}
		}
		#endregion

		#region Methods
		#region Auxiliar
		private void _FillCivilStateCombo()
		{
			List<KeyValuePair<string, ECivilState>> states = new List<KeyValuePair<string, ECivilState>>();

			foreach (ECivilState type in Enum.GetValues(typeof(ECivilState)))
				states.Add(new KeyValuePair<string, ECivilState>(type.GetDescription(), type));

			cbxCivilState.DisplayMember = "Key";
			cbxCivilState.ValueMember = "Value";
			cbxCivilState.DataSource = states;
		}
		private void _FillDocumentTypeCombo()
		{
			List<KeyValuePair<string, EDocumentType>> types = new List<KeyValuePair<string, EDocumentType>>();

			foreach (EDocumentType type in Enum.GetValues(typeof(EDocumentType)))
				types.Add(new KeyValuePair<string, EDocumentType>(type.GetDescription(), type));

			cbxDocumentType.DisplayMember = "Key";
			cbxDocumentType.ValueMember = "Value";
			cbxDocumentType.DataSource = types;
		}
		private void _FillMembershipTypeCombo()
		{
			List<KeyValuePair<string, EMembershipType>> types = new List<KeyValuePair<string, EMembershipType>>();

			foreach (EMembershipType type in Enum.GetValues(typeof(EMembershipType)))
				if (type != EMembershipType.Unknown)
					types.Add(new KeyValuePair<string, EMembershipType>(type.GetDescription(), type));

			cboMembersyType.DisplayMember = "Key";
			cboMembersyType.ValueMember = "Value";
			cboMembersyType.DataSource = types;
		}
		private void _FillDisruptionTypeCombo()
		{
			List<KeyValuePair<string, EDisruptionType>> types = new List<KeyValuePair<string, EDisruptionType>>();

			foreach (EDisruptionType type in Enum.GetValues(typeof(EDisruptionType)))
				types.Add(new KeyValuePair<string, EDisruptionType>(type.GetDescription(), type));

			cboDisruption.DisplayMember = "Key";
			cboDisruption.ValueMember = "Value";
			cboDisruption.DataSource = types;
		}
		#endregion

		#region Event Handlers
		private void cbxDocumentType_SelectedValueChanged(object sender, EventArgs e)
		{
			EDocumentType type = cbxDocumentType.SelectedValue != null ? ((EDocumentType)cbxDocumentType.SelectedValue) : EDocumentType.Unknown;
			string mask = "";

			switch (type)
			{
				case EDocumentType.Unknown:
					mtbDocumentNumber.Enabled = false;
					break;
				case EDocumentType.CPF:
					mask = "000.000.000-00";
					mtbDocumentNumber.Enabled = true;
					break;
				case EDocumentType.CNPJ:
					mask = "00.000.000/0000-00";
					mtbDocumentNumber.Enabled = true;
					break;
				default:
					break;
			}

			if (!mtbDocumentNumber.Mask.Equals(mask))
			{
				mtbDocumentNumber.Text = "";
				mtbDocumentNumber.Mask = mask;
			}
		}
		private void cboDisruption_SelectedValueChanged(object sender, EventArgs e)
		{
			dtpDisruptionDate.Enabled = cboDisruption.SelectedValue != null && ((EDisruptionType)cboDisruption.SelectedValue) != EDisruptionType.Unknown;
		}
		#endregion

		#region Overridens
		public override bool ConflictsWith(ConflictableForm form)
		{
			bool conflicts = false;

			if (form.GetType() == this.GetType())
			{
				// Só conflita se for inserção ou se for edição do mesmo elemento
				FEditMember fEdit = form as FEditMember;

				if (fEdit.InitialState == this.InitialState)
				{
					if (this.InitialState == EFormState.Edit)
						conflicts = true;
					else if (this._CurrentEntity != null && fEdit._CurrentEntity != null && this._CurrentEntity.Id == fEdit._CurrentEntity.Id)
						conflicts = true;
				}
			}

			return conflicts;
		}
		protected override void OnLoad(EventArgs e)
		{
			_FillCivilStateCombo();
			_FillMembershipTypeCombo();
			_FillDisruptionTypeCombo();
			_FillDocumentTypeCombo();

			base.OnLoad(e);
		}
		protected override void _RefreshConditionalLocks()
		{
			mtbDocumentNumber.Enabled = cbxDocumentType.SelectedValue != null && ((EDocumentType)cbxDocumentType.SelectedValue) != EDocumentType.Unknown;
			dtpDisruptionDate.Enabled = cboDisruption.SelectedValue != null && ((EDisruptionType)cboDisruption.SelectedValue) != EDisruptionType.Unknown;
		}

		#region Loading
		protected override Contributor _LoadEntity(int id)
		{
			return
				Provider.GetContributor(id);
		}
		protected override void _FillEntity(Contributor entity)
		{
			if (entity != null)
			{
				_Id = entity.Id;

				uAddressControl1.FillAddress(entity.Address);

				txtName.Text = entity.Name;
				cbxDocumentType.SelectedValue = entity.DocumentType.HasValue ? entity.DocumentType.Value : EDocumentType.Unknown;
				mtbDocumentNumber.Text = entity.DocumentNumber;
				mtbPhone.Text = entity.Phone;
				mtbCellPhone.Text = entity.CellPhone;

				if (entity is Frequenter)
				{
					Frequenter frequenter = entity as Frequenter;
					if (frequenter.BirthdayDate.HasValue)
					{
						dtpBornDate.Value = frequenter.BirthdayDate.Value;
						dtpBornDate.Checked = true;
					}
					else
						dtpBornDate.Checked = false;

					cbxCivilState.SelectedValue = frequenter.CivilState;
				}
				if (entity.Type == EContributorType.Member || entity.Type == EContributorType.Away)
				{
					Member member = entity as Member;
					cboMembersyType.SelectedValue = member.MembershipType;
					dtpMembersyDate.Value = member.MembershipDate;

					if (member.DisruptionDate.HasValue)
					{
						dtpDisruptionDate.Value = member.DisruptionDate.Value;
						dtpDisruptionDate.Checked = true;
					}
					else
						dtpDisruptionDate.Checked = false;

					cboDisruption.SelectedValue = member.DisruptionType;


					if (member.DisruptionDate.HasValue)
						dtpDisruptionDate.Value = member.DisruptionDate.Value;
					else
						dtpDisruptionDate.Text = "";
				}
				else if (entity.Type == EContributorType.Visitor)
				{
					Visitor visitor = entity as Visitor;

					txtChurchOrigin.Text = visitor.OriginChurch != null ? visitor.OriginChurch : string.Empty;
				}
			}
		}
		protected override object _LoadSpecificData()
		{
			return
				Provider.GetAddresses();
		}
		protected override void _FillSpecificData(object result)
		{
			uAddressControl1.Addresses = (Dictionary<string, Address>)result;
		} 
		#endregion
		
		#region Commit
		protected override Contributor _BuildEntity()
		{
			ExceptionsContainer exs = new ExceptionsContainer();

			// Se tem um tipo de documento selecionado e o valor digitado não bate com a máscara
			if ((EDocumentType?)cbxDocumentType.SelectedValue != EDocumentType.Unknown && !mtbDocumentNumber.MaskCompleted)
				exs.Add(new ValidationError("InvalidDocumentNumber", "Número de documento inválido."));
			if (mtbCellPhone.GetValue().Length > 0 && !mtbCellPhone.MaskCompleted)
				exs.Add(new ValidationError("InvalidCellPhoneNumber", "O valor digitado não corresponde a um telefone válido."));
			if (mtbPhone.GetValue().Length > 0 && !mtbPhone.MaskCompleted)
				exs.Add(new ValidationError("InvalidPhoneNumber", "O valor digitado não corresponde a um telefone válido."));

			Contributor c = null;

			if (dtpDisruptionDate.Checked)
				c = Contributor.Create(EContributorType.Away);
			else
				c = Contributor.Create(Type);

			c.Id = _Id;

			c.Name = txtName.Text;
			c.DocumentType = (EDocumentType?)cbxDocumentType.SelectedValue;
			c.DocumentNumber = mtbDocumentNumber.Text;

			c.Phone = mtbPhone.Text;
			c.CellPhone = mtbCellPhone.Text;

			if (c is Frequenter)
			{
				Frequenter frequenter = c as Frequenter;

				frequenter.BirthdayDate = dtpBornDate.Checked ? dtpBornDate.Value : (DateTime?)null;
				frequenter.CivilState = (ECivilState)cbxCivilState.SelectedValue;
			}
			if (c.Type == EContributorType.Member)
			{
				Member member = c as Member;
				member.MembershipType = (EMembershipType)cboMembersyType.SelectedValue;
				member.MembershipDate = dtpMembersyDate.Value;

				member.DisruptionDate = dtpDisruptionDate.Checked ? dtpDisruptionDate.Value : (DateTime?)null;
				member.DisruptionType = (EDisruptionType)cboDisruption.SelectedValue;
			}
			else if (c.Type == EContributorType.Visitor)
			{
				Visitor visitor = c as Visitor;

				visitor.OriginChurch = txtChurchOrigin.Text;
			}

			try
			{
				c.Address = uAddressControl1.BuildAddress();
			}
			catch (Exception e)
			{
				exs.Add(e);
			}

			if (exs.Count() > 0)
				throw exs;

			return c;
		}
		protected override ExceptionsContainer _ValidateEntity(Contributor entity)
		{
			return ContributorValidator.ValidateContributor(entity);
		}
		protected override int _SaveEntity(Contributor entity)
		{
			IManagementServicesProvider manProv = _Manager.ServicesProvider.CreateManagementServicesProvider();
			int id = entity.Id;

			if (entity.Id > 0)
				manProv.UpdateContributor(entity);
			else
				id = manProv.InsertContributor(entity);

			return id;
		}
		#endregion
		#endregion 
		#endregion
	}
}
